﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Windows.Forms;
using ApplicationLibrary;
using ApplicationLibrary.DBManager;
using ApplicationLibrary.ExtendedControls;
using ApplicationLibrary.SqlConnector;
using Plumber.Accounting.ModuleData;
using Plumber.Masters.ModuleData;
using Plumber.Sales.ModuleData;
using Plumber.Accounting.Preferences;
using ApplicationLibrary.Preferences;

namespace Plumber.Accounting.Forms
{
    public partial class JournalEntriesSalePurchase : ApplicationLibrary.DBManager.DocumentForm
    {
        public BindableOject<bool> IsEditable = null;
        private ComboBoxManager accountTypesFrom = null;
        private ComboBoxManager accountTypesTo = null;
        private bool bForcedCloseOpen = false;
        private Dictionary<string, Totals> DocumentList = null;
        private DRJournalEntryTotal dRJETotal = null;
        private DRJournalEntryTotalWithoutMe dRJETotNoMe = null;
        private DRSaleJournalEntryTotalByType dRJETotByType = null;
        private DRMasterType dRMasterType = null;
        private DRMasters dRMaster = null;
        private DRSalesInvoices dRSalesInvoices = null;
        private DRTaxCode dRTaxCode = null;
        private bool FromPrepareAuxData = false;
        private bool IsInLoad = false;
        private string oldText = string.Empty;
        private RRJournalEntryAfterMe rrJENotMe = null;
        private RUJournalEntryWithoutMe rUJENotMe = null;
        private AccountingPref AccountingPref = null;
        private EnumsManager<TaxRegisterType> eTaxRegister = null;
        private EnumsManager<InvoiceType> eInvoiceType = null; 

        public JournalEntriesSalePurchase()
            : base(Properties.Resources.FN_JournalEntries)
        {
            InitializeComponent();
            AccountingPref = new PreferencesManager<AccountingPref>(this.Name, null).ReadPreference();
            keyControl = fncJournalNo;
        }

        public bool DontUpdateSale { set; private get; }

        #region Scrounger Access
        public ExtendedDataGridView GetDataGrid { get { return dgwJournalEntries; } }
        public ExtendedDataGridView GetCastleTax { get { return dgwCastleTax; } }
        public TextBox GetDescription { get { return txtDescription; } }
        public TextBox GetDocNo { get { return txtDocNo; } }
        public Masters.Library.MasterTypeComboBox GetMasterType { get { return cbbType; } }
        public ApplicationLibrary.CounterManager.RadarCodesCtrl GetCode { get { return rdrCode; } }
        public DBComboBox GetTaxRegister { get { return cbbTaxRegister; } }
        public DBComboBox GetTemplate { get { return cbbTemplate; } }
        public void LoadTemplate() { btnLoad_Click(this, EventArgs.Empty); }
        public void ClearEmptyRow() { ClearEmptyDetailRow(); }
        public DBComboBox GetDocumentType { get { return cbbDocType; } }
        public TextBox GetInvoice { get {return txtInvoice;}}

        public CalendarTextBox GetPostingDate { get { return ctbDate; } }
        public CalendarTextBox GetDocDate { get { return ctbDocDate; } } 
        #endregion

        #region Virtual Method
        protected override void FocusOnNew()
        {
        }

        protected override IRadarParameters GetKeyFromDocument()
        {
            return new RadarJournalEntryParam(fncJournalNo.Text);
        }

        protected override bool OnAfterAddNew()
        {
            IsEditable.Value = true;
            rdrCode.DeattachAll();
            return base.OnAfterAddNew();
        }

        protected override void OnAttachData()
        {
            dbManager = new dbmanagerJournalEntries("JournalEntriesSalePurchaseForm", new RadarJournalEntry(true), this);
            dbManager.AddMaster(this, PL_JournalEntry.Name, true);
            dbManager.AddSlave(PL_JournalEntryDetail.Name, true);
            dbManager.AddRelation("JournalEntryDetail", PL_JournalEntry.JournalNo, PL_JournalEntryDetail.JournalNo, true);
            dbManager.AddSlave(PL_JournalEntryTaxDetail.Name, true);
            dbManager.AddRelation("JournalEntryTaxDetail", PL_JournalEntry.JournalNo, PL_JournalEntryTaxDetail.JournalNo, true);

            dRJETotal = new DRJournalEntryTotal();
            dRJETotNoMe = new DRJournalEntryTotalWithoutMe();
            dRJETotByType = new DRSaleJournalEntryTotalByType();
            rUJENotMe = new RUJournalEntryWithoutMe();
            dRSalesInvoices = new DRSalesInvoices(true);
            dRMasterType = new DRMasterType(DRMasterType.Module.All);
            dRMaster = new DRMasters(false);
            dRTaxCode = new DRTaxCode(false);
            DocumentList = new Dictionary<string, Totals>();
            cbbTemplate.AttachDataReader<string>(new RRJETemplate(true), PL_JETemplate.Template, PL_JETemplate.Description, true);
            eTaxRegister = new EnumsManager<TaxRegisterType>(cbbTaxRegister);
            eInvoiceType = new EnumsManager<InvoiceType>(cbbDocType);

            ject_TaxCode.AttachDataReader(new RRTaxCode(), PL_TaxCode.Code, PL_TaxCode.Description);
            ject_RestraintCode.AttachDataReader(new RRTaxCode(), PL_TaxCode.Code, PL_TaxCode.Description, true);

            accountTypesFrom = new ComboBoxManager();
            accountTypesTo = new ComboBoxManager();
            IsEditable = new BindableOject<bool>();

            RRMasterType rrMasterType = new RRMasterType();
            rrMasterType.Find();
            accountTypesFrom.AddValue<string>(null, "");
            accountTypesTo.AddValue<string>(null, "");

            for (int t = 0; t < rrMasterType.Count; t++)
            {
                if (rrMasterType.GetValue<MasterTypes>(PL_MasterType.MasterType, t) != MasterTypes.E_Administrator)
                {
                    accountTypesFrom.AddValue(rrMasterType.GetValue<string>(PL_MasterType.Code, t), rrMasterType.GetValue<string>(PL_MasterType.Description, t));
                    accountTypesTo.AddValue(rrMasterType.GetValue<string>(PL_MasterType.Code, t), rrMasterType.GetValue<string>(PL_MasterType.Description, t));
                }
            }
            accountTypesFrom.AttachTo(jec_Type);

            fncJournalNo.AttachCounterType(GlobalInfo.GetCounter(Properties.Resources.CN_JournalEntry), GlobalInfo.CurrentDate, dbManager.Transaction);

            ntbTo.Prefix = Properties.Resources.CurrencySimbol;
            ntbFrom.Prefix = Properties.Resources.CurrencySimbol;

            DRMasterTypeByType dRMasterTypeByType = new DRMasterTypeByType();

            if (dRMasterTypeByType.Find(MasterTypes.E_Condominium))
            {
                string condomType = dRMasterTypeByType.GetValue<string>(PL_MasterType.Code, 0);
                rdrCode.RadarForm = new RadarMasterForm(condomType, RadarMasterForm.Module.All){DecodeAddress=true};
                rdrCode.AttachCodeType(condomType);
                rdrCode.RadarForm.EnableAddOnFly = true;
                rdrCode.DescriptionControl = txtDescription;
                cbbType.AttachDataReader(new RRMasterTypeForJEPurchase());
            }
        }

        protected override bool OnBeforeDelete()
        {
            if (!base.OnBeforeDelete())
                return false;

            if (AccountingPref.LockDocumentPayed && !CandDeleteRegistration())
            {
                MyMessageBox(Properties.Resources.Msg_JEAlredyPayed);
                return false;
            }

            return UpdateForSaveDelete(true);
        }

        protected override bool OnBeforeSave()
        {
            //dgwJournalEntries.Refresh();
            if (ntbFrom.Double != ntbTo.Double)
                if (MyMessageBox(Properties.Resources.Msg_JournalNotBalanced, Properties.Resources.Warning, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == System.Windows.Forms.DialogResult.No)
                    return false;

            if (ctbDate.Today == ctbDate.EmptyDate)
            {
                MyMessageBox(Properties.Resources.Msg_MissingJournalDate, Properties.Resources.Warning, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return false;
            }

            if ((int)cbbTaxRegister.SelectedValue == TaxRegisterType.E_NORegister.Int())
            {
                MyMessageBox(Properties.Resources.Msg_MissingTaxRegister, Properties.Resources.Warning, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return false;
            }

            if (ctbDocDate.Today == ctbDocDate.EmptyDate)
            {
                MyMessageBox(Properties.Resources.Msg_MissingDocumentDate, Properties.Resources.Warning, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return false;
            }

            if (dRMasterType.Find(cbbType.GetValue<string>()) && dRMasterType.GetValue<bool>(PL_MasterType.DocNoRequired) && txtDocNo.Text == string.Empty)
            {
                MyMessageBox(Properties.Resources.Msg_MissingDocNo, Properties.Resources.Warning, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return false;
            }

            if (HasRowAtZero())
            {
                MyMessageBox(Properties.Resources.Msg_RowAtZero, Properties.Resources.Warning, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return false;
            }

            if (HasEmptyRow())
            {
                MyMessageBox(Properties.Resources.Msg_MissingRows, Properties.Resources.Warning, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return false;
            }

            if (HasEmptyTaxRow())
            {
                MyMessageBox(Properties.Resources.Msg_MissingTax, Properties.Resources.Warning, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return false;
            }

            UpdateForSaveDelete(false);

            return base.OnBeforeSave();
        }

        protected override void OnBindData()
        {
            BindControl(fncJournalNo, PL_JournalEntry.JournalNo, NullValue.NotSet, Findable.YES);
            BindControl(ctbDate, PL_JournalEntry.PostingDate);
            BindControl(ckbClose);
            BindControl(cbbType, PL_JournalEntry.Type, "SelectedValue", NullValue.NotSet, Findable.YES);
            BindControl(rdrCode, PL_JournalEntry.Code, Findable.YES);
            BindControl(txtDocNo, PL_JournalEntry.DocumentNo, Findable.YES);
            BindControl(ctbDocDate, PL_JournalEntry.DocumentDate);
            BindControl(txtDescription, PL_JournalEntry.Description, Findable.YES);
            BindControl(cbbTaxRegister, PL_JournalEntry.TaxRegister, "SelectedValue");
            BindControl(cbbDocType, PL_JournalEntry.InvoiceType, "SelectedValue");
            BindControl(txtInvoice, PL_JournalEntry.InvoiceNo);

            BindObject(IsEditable, PL_JournalEntry.Editable);

            dgwJournalEntries.AutoGenerateColumns = false;
            dgwJournalEntries.DataSource = dbManager.SlaveBinding("JournalEntryDetail");

            BindColumn(jec_Line, PL_JournalEntryDetail.Line);
            BindColumn(jec_Type, PL_JournalEntryDetail.Type);
            BindColumn(jec_Code, PL_JournalEntryDetail.Code);
            BindColumn(jec_DocumentNo, PL_JournalEntryDetail.DocumentNo);
            BindColumn(jec_From, PL_JournalEntryDetail.From);
            BindColumn(jec_To, PL_JournalEntryDetail.To);
            BindColumn(jec_FromInvoice, PL_JournalEntryDetail.FromInvoice);
            BindColumn(jec_Closed, PL_JournalEntryDetail.Close);
            BindColumn(jec_InvoiceNo, PL_JournalEntryDetail.InvoiceNo);

            BindColumn(jec_Description, PL_JournalEntryDetail.Description);

            dgwJournalEntries.AddColumnChangeValue(PL_JournalEntryDetail.Type, new ExtendedDataGridView.DataGridViewValueChangeEventHandler(dgwJournalEntries_Type));
            dgwJournalEntries.AddColumnChangeValue(PL_JournalEntryDetail.From, new ExtendedDataGridView.DataGridViewValueChangeEventHandler(dgwJournalEntries_FromAmountChange));
            dgwJournalEntries.AddColumnChangeValue(PL_JournalEntryDetail.To, new ExtendedDataGridView.DataGridViewValueChangeEventHandler(dgwJournalEntries_ToAmountChange));
            dgwJournalEntries.AddColumnValidator(PL_JournalEntryDetail.Code, new ExtendedDataGridView.DataGridViewColumnValidatingEventHandler(dgwJournalEntries_Code));
            dgwJournalEntries.DataGridViewRowEnter += new DataGridViewCellEventHandler(dgwJournalEntries_DataGridViewRowEnter);
            dgwJournalEntries.DataGridViewRowRemoved += new DataGridViewRowsRemovedEventHandler(dgwJournalEntries_DataGridViewRowRemoved);
            dgwJournalEntries.DataGridViewRowAdded += new DataGridViewRowsAddedEventHandler(dgwJournalEntries_DataGridViewRowAdded);
            dgwJournalEntries.DataGridViewRowValidating += new DataGridViewCellCancelEventHandler(dgwJournalEntries_DataGridViewRowValidating);
            dgwJournalEntries.RowIndex = PL_JournalEntryDetail.Line;
            BindControl(dgwJournalEntries);

            dgwCastleTax.AutoGenerateColumns = false;
            dgwCastleTax.DataSource = dbManager.SlaveBinding("JournalEntryTaxDetail");

            BindColumn(ject_Line, PL_JournalEntryTaxDetail.Line);
            BindColumn(ject_TaxCode, PL_JournalEntryTaxDetail.TaxCode);
            BindColumn(ject_taxPerc, PL_JournalEntryTaxDetail.TaxPerc);
            BindColumn(ject_Amount, PL_JournalEntryTaxDetail.Amount);
            BindColumn(ject_Tax, PL_JournalEntryTaxDetail.Tax);
            BindColumn(ject_Deduction, PL_JournalEntryTaxDetail.Deduction);
            BindColumn(ject_BankRestraint, PL_JournalEntryTaxDetail.BankRestraint);
            BindColumn(ject_Restraint, PL_JournalEntryTaxDetail.Restraint);
            BindColumn(ject_RestraintCode, PL_JournalEntryTaxDetail.RestraintCode);
            BindColumn(ject_RestraintAmount, PL_JournalEntryTaxDetail.RestraintAmount);
            BindColumn(ject_RestrPerc, PL_JournalEntryTaxDetail.RestraintPerc);

            BindColumn(ject_Total, PL_JournalEntryTaxDetail.Total);
            dgwCastleTax.RowIndex = PL_JournalEntryTaxDetail.Line;
            BindControl(dgwCastleTax);

            dgwCastleTax.AddColumnChangeValue(PL_JournalEntryTaxDetail.TaxCode, new ExtendedDataGridView.DataGridViewValueChangeEventHandler(dgwCastleTax_TaxCode));
            dgwCastleTax.AddColumnChangeValue(PL_JournalEntryTaxDetail.Amount, new ExtendedDataGridView.DataGridViewValueChangeEventHandler(dgwCastleTax_Amount));
            dgwCastleTax.AddColumnChangeValue(PL_JournalEntryTaxDetail.Tax, new ExtendedDataGridView.DataGridViewValueChangeEventHandler(dgwCastleTax_Tax));
            dgwCastleTax.AddColumnChangeValue(PL_JournalEntryTaxDetail.Total, new ExtendedDataGridView.DataGridViewValueChangeEventHandler(dgwCastleTax_Total));
            dgwCastleTax.AddColumnChangeValue(PL_JournalEntryTaxDetail.Restraint, new ExtendedDataGridView.DataGridViewValueChangeEventHandler(dgwCastleTax_Restraint));
            dgwCastleTax.AddColumnChangeValue(PL_JournalEntryTaxDetail.RestraintCode, new ExtendedDataGridView.DataGridViewValueChangeEventHandler(dgwCastleTax_RestraintCode));
            dgwCastleTax.DataGridViewRowEnter += new DataGridViewCellEventHandler(dgwCastleTax_DataGridViewRowEnter);
            //dgwCastleTax.AddColumnChangeValue(PL_JournalEntryTaxDetail.RestraintCode, new ExtendedDataGridView.DataGridViewValueChangeEventHandler(dgwCastleTax_RestraintAmount));

            BindControl(cbbTemplate);
            BindControl(btnLoad);
            BindControl(ntbFrom);
            BindControl(ntbTo);
            BindCounter(fncJournalNo);
        }

        void dgwCastleTax_DataGridViewRowEnter(object sender, DataGridViewCellEventArgs e)
        {
            bool IsReadonly = !dgwCastleTax.GetValue<bool>(e.RowIndex, PL_JournalEntryTaxDetail.Restraint);
            dgwCastleTax[PL_JournalEntryTaxDetail.RestraintAmount].ReadOnly = IsReadonly;
            dgwCastleTax[PL_JournalEntryTaxDetail.RestraintCode].ReadOnly = IsReadonly;
        }

        protected override void OnDisableControlsForEdit()
        {
            txtInvoice.Enabled = false;
        }

        protected override void OnDisableControlsForNew()
        {
            ctbDate.Today = GlobalInfo.CurrentDate;
            txtInvoice.Enabled = false;
        }

        protected override void OnPrepareAuxData()
        {
            FromPrepareAuxData = true;
            ckbClose.Checked = GetRowClosed();
            FromPrepareAuxData = false;
            CalculateTotal();
            UpdateCastleTax();
        }

        private void CalculateTotal()
        {
            ntbFrom.Double = 0;
            ntbTo.Double = 0;
            foreach (DataGridViewRow dr in dgwJournalEntries.Rows)
            {
                if (!dr.IsNewRow)
                {
                    ntbFrom.Double += DataGridViewRowValues.GetValue<double>(dr, PL_JournalEntryDetail.From);
                    ntbTo.Double += DataGridViewRowValues.GetValue<double>(dr, PL_JournalEntryDetail.To);
                }
            }
        }

        private void UpdateCastleTax()
        {
            dgwCastleTax.NoMessage = true;
            foreach (DataGridViewRow dr in dgwCastleTax.Rows)
            {
                if (!dr.IsNewRow)
                {
                    if (!string.IsNullOrEmpty(DataGridViewRowValues.GetValue<string>(dr, PL_JournalEntryTaxDetail.Tax)) &&
                        DataGridViewRowValues.GetValue<double>(dr, PL_JournalEntryTaxDetail.TaxPerc) == 0)
                    {

                        dRTaxCode.Find(DataGridViewRowValues.GetValue<string>(dr, PL_JournalEntryTaxDetail.TaxCode));
                        DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryTaxDetail.TaxPerc, dRTaxCode.GetValue<double>(PL_TaxCode.Percent));
                    }

                    double total = DataGridViewRowValues.GetValue<double>(dr, PL_JournalEntryTaxDetail.Amount) +
                                    DataGridViewRowValues.GetValue<double>(dr, PL_JournalEntryTaxDetail.Tax);

                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryTaxDetail.Total, total);
                }
            }
            dgwCastleTax.NoMessage = false;
        }

        private bool CandDeleteRegistration()
        {
            bool payed = false;
            for (int t = 0; t < dbManager.GetDataTable(PL_JournalEntryDetail.Name).Rows.Count && !payed; t++)
            {
                string docNo = dbManager.GetColumn<string>(PL_JournalEntryDetail.DocumentNo, t);
                if (string.IsNullOrEmpty(docNo))
                    continue;

                string type = dbManager.GetColumn<string>(PL_JournalEntryDetail.Type, t);
                string code = dbManager.GetColumn<string>(PL_JournalEntryDetail.Code, t).ToString();

                string JEno = "", cod = "";
                double from, to;
                payed = SearchPayment(type, docNo, ref JEno, out from, out to, out cod);
            }
            return !payed;
        }

        private void dgwJournalEntries_DataGridViewRowAdded(object sender, DataGridViewRowsAddedEventArgs e)
        {
            //if (SilentMode || txtDescription.Text == string.Empty || IsInLoad)
            //    return;
            //int nRow = e.RowIndex < e.RowCount
            //                ? e.RowIndex
            //                : e.RowIndex - 1;
            //dgwJournalEntries.SetValue<string>(nRow, PL_JournalEntryDetail.Description, txtDescription.Text);
        }

        private void dgwJournalEntries_DataGridViewRowEnter(object sender, DataGridViewCellEventArgs e)
        {
            DoChangingRow(e);
            dgwJournalEntries[PL_JournalEntryDetail.Description].ReadOnly = string.IsNullOrEmpty(dgwJournalEntries.GetValue<string>(e.RowIndex, PL_JournalEntryDetail.Type));
        }

        private void dgwJournalEntries_DataGridViewRowRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
        {
            CalculateTotal();
        }

        private void dgwJournalEntries_DataGridViewRowValidating(object sender, DataGridViewCellCancelEventArgs e)
        {
            if (DocumentMode == DBMode.Browse || IsInLoad)
                return;

            string typeCode = dgwJournalEntries.GetValue<string>(e.RowIndex, PL_JournalEntryDetail.Type);
            if (string.IsNullOrEmpty(typeCode))
                return;
            if (!dRMasterType.Find(typeCode))
                return;

            if (dRMasterType.GetValue<CodeMode>(PL_MasterType.CodeMode) == CodeMode.E_MustExists &&
                dgwJournalEntries.GetValue<string>(e.RowIndex, PL_JournalEntryDetail.Code) == string.Empty)
            {
                e.Cancel = true;
                string mess = string.Format(Properties.Resources.Msg_MissingCode, dRMasterType.GetValue<string>(PL_MasterType.Description, 0));
                MyMessageBox(this, mess,
                Properties.Resources.Error,
                MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (dRMasterType.GetValue<bool>(PL_MasterType.DocNoRequired) &&
                dgwJournalEntries.GetValue<string>(e.RowIndex, PL_JournalEntryDetail.DocumentNo) == string.Empty)
            {
                e.Cancel = true;
                MyMessageBox(this, Properties.Resources.Msg_MissingDocNo,
                Properties.Resources.Error,
                MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (DocumentMode == DBMode.Browse)
                return;
        }
        private bool SearchPayment(string type, string docNo, ref string JENo, out double from, out double to, out string code)
        {
            from = to = 0;
            code = string.Empty;

            if (rrJENotMe == null)
                rrJENotMe = new RRJournalEntryAfterMe();

            if (rrJENotMe.Find(type, docNo, fncJournalNo.Text))
            {
                for (int t = 0; t < rrJENotMe.Count; t++)
                {
                    if (rrJENotMe.GetValue<double>(PL_JournalEntryDetail.To, t) != 0)
                    {
                        to += rrJENotMe.GetValue<double>(PL_JournalEntryDetail.To, t);
                    }
                    if (rrJENotMe.GetValue<double>(PL_JournalEntryDetail.From, t) != 0)
                    {
                        JENo = rrJENotMe.GetValue<string>(PL_JournalEntryDetail.JournalNo, t);
                        code = rrJENotMe.GetValue<string>(PL_JournalEntryDetail.Code, t);
                        from += rrJENotMe.GetValue<double>(PL_JournalEntryDetail.From, t);
                    }
                }
            }

            return from != 0 && to != 0;
        }

        private void UpdateAllJEntry(string docNo, string type, string code, string journalNo, double totalFrom, double totalTo)
        {
            bool closed = totalFrom == totalTo;
            if (rUJENotMe.Find(docNo, type, code, journalNo))
            {
                for (int t = 0; t < rUJENotMe.Count; t++)
                    rUJENotMe.SetValue<bool>(PL_JournalEntryDetail.Close, t, closed);
            }
            rUJENotMe.Update();

            // Mi cerco nel documento corrente e mi aggiorno
            for (int t = 0; t < dbManager.GetDataTable(PL_JournalEntryDetail.Name).Rows.Count && !bForcedCloseOpen; t++)
            {
                if (dbManager.GetColumn<string>(PL_JournalEntryDetail.DocumentNo, t) == docNo)
                    dbManager.SetColumn<bool>(PL_JournalEntryDetail.Close, t, closed);
            }
        }

        private bool UpdateForSaveDelete(bool isDelete)
        {
            txtDescription.Focus();
            dgwJournalEntries.EndEdit();
            if (dgwJournalEntries.CurrentCell!= null && dgwJournalEntries.CurrentCell.RowIndex != 0)
                dgwJournalEntries.CurrentCell = dgwJournalEntries[PL_JETemplateDetail.From, 0];

            DocumentList.Clear();

            for (int t = 0; t < dbManager.GetDataTable(PL_JournalEntryDetail.Name).Rows.Count; t++)
            {
                DataRowState drState = dbManager.GetDataRow(PL_JournalEntryDetail.Name, t).RowState;
                if ((drState == DataRowState.Unchanged && !isDelete) ||
                    string.IsNullOrEmpty(dbManager.GetColumn<string>(PL_JournalEntryDetail.DocumentNo, t)))
                    continue;

                //if (drState == DataRowState.Modified &&
                //        dbManager.GetColumn<double>(PL_JournalEntryDetail.From, t, DataRowVersion.Original) ==  dbManager.GetColumn<double>(PL_JournalEntryDetail.From, t) &&
                //        dbManager.GetColumn<double>(PL_JournalEntryDetail.To, t, DataRowVersion.Original) ==  dbManager.GetColumn<double>(PL_JournalEntryDetail.To, t))
                //    continue;

                string docNo = dbManager.GetColumn<string>(PL_JournalEntryDetail.DocumentNo, t);
                string type = dbManager.GetColumn<string>(PL_JournalEntryDetail.Type, t);
                string code = dbManager.GetColumn<string>(PL_JournalEntryDetail.Code, t).ToString();

                string key = string.Concat(docNo, " ", type, " ", code);

                if (!DocumentList.ContainsKey(key))
                    DocumentList.Add(key, new Totals(docNo, type, code, 0, 0));

                double totFrom = 0, totTo = 0;
                switch (drState)
                {
                    case DataRowState.Added:
                        if (isDelete)
                        {
                            totFrom -= dbManager.GetColumn<double>(PL_JournalEntryDetail.From, t);
                            totTo -= dbManager.GetColumn<double>(PL_JournalEntryDetail.To, t);
                        }
                        else
                        {
                            totFrom += dbManager.GetColumn<double>(PL_JournalEntryDetail.From, t);
                            totTo += dbManager.GetColumn<double>(PL_JournalEntryDetail.To, t);
                        }
                        break;

                    case DataRowState.Modified:
                        if (isDelete)
                        {
                            totFrom -= dbManager.GetColumn<double>(PL_JournalEntryDetail.From, t);
                            totTo -= dbManager.GetColumn<double>(PL_JournalEntryDetail.To, t);
                        }
                        else
                        {
                            totFrom -= dbManager.GetColumn<double>(PL_JournalEntryDetail.From, t, DataRowVersion.Original);
                            totTo -= dbManager.GetColumn<double>(PL_JournalEntryDetail.To, t, DataRowVersion.Original);
                            totFrom += dbManager.GetColumn<double>(PL_JournalEntryDetail.From, t);
                            totTo += dbManager.GetColumn<double>(PL_JournalEntryDetail.To, t);
                        }
                        break;

                    case DataRowState.Unchanged:
                        if (isDelete)
                            totFrom -= dbManager.GetColumn<double>(PL_JournalEntryDetail.From, t, DataRowVersion.Original);
                        totTo -= dbManager.GetColumn<double>(PL_JournalEntryDetail.To, t, DataRowVersion.Original);
                        break;

                    case DataRowState.Deleted:
                        totFrom -= dbManager.GetColumn<double>(PL_JournalEntryDetail.From, t, DataRowVersion.Original);
                        totTo -= dbManager.GetColumn<double>(PL_JournalEntryDetail.To, t, DataRowVersion.Original);
                        break;
                }

                DocumentList[key].totFrom += totFrom;
                DocumentList[key].totTo += totTo;
            }

            if (DocumentList.Count > 0)
                UpdateJournalEntries();

            return true;
        }

        private void UpdateJournalEntries()
        {
            foreach (KeyValuePair<string, Totals> item in DocumentList)
                if (item.Value.totFrom != 0 || item.Value.totTo != 0)
                {
                    // Mi faccio restituire il totale senza questa registrazione
                    dRJETotNoMe.Find(item.Value.DocNo, item.Value.Type, item.Value.Code, fncJournalNo.Text);
                    double totalFrom = dRJETotNoMe.GetValue<double>(PL_JournalEntryDetail.From) + item.Value.totFrom;
                    double totalTo = dRJETotNoMe.GetValue<double>(PL_JournalEntryDetail.To) + item.Value.totTo;

                    UpdateAllJEntry(item.Value.DocNo, item.Value.Type, item.Value.Code, fncJournalNo.Text, totalFrom, totalTo);
                }
        }
        #endregion

        public int AddNewRow(string masterType, string docNo, string code, double from, double to, string desc, bool fromInvoie, bool closed, string invoiceNo)
        {
            DataRowView drw = dgwJournalEntries.AddNewRow(PL_JournalEntryDetail.Line);

            DataRowViewValues.SetValue<string>(drw, PL_JournalEntryDetail.Type, masterType);
            DataRowViewValues.SetValue<string>(drw, PL_JournalEntryDetail.DocumentNo, docNo);
            DataRowViewValues.SetValue<string>(drw, PL_JournalEntryDetail.Code, code);
            DataRowViewValues.SetValue<double>(drw, PL_JournalEntryDetail.From, from);
            DataRowViewValues.SetValue<double>(drw, PL_JournalEntryDetail.To, to);
            DataRowViewValues.SetValue<string>(drw, PL_JournalEntryDetail.Description, desc);
            DataRowViewValues.SetValue<bool>(drw, PL_JournalEntryDetail.FromInvoice, fromInvoie);
            DataRowViewValues.SetValue<bool>(drw, PL_JournalEntryDetail.Close, closed);
            DataRowViewValues.SetValue<string>(drw, PL_JournalEntryDetail.InvoiceNo, invoiceNo);
            return DataRowViewValues.GetValue<int>(drw, PL_JournalEntryDetail.Line);
        }

        public int AddCastleRow(string taxcode, double amount, double tax, bool bankRestraint, bool deduction, bool restraint, string restraintcode, double restraintamount)
        {
            DataRowView drw = dgwCastleTax.AddNewRow(PL_JournalEntryTaxDetail.Line);
            DataRowViewValues.SetValue<string>(drw, PL_JournalEntryTaxDetail.TaxCode, taxcode);
            DataRowViewValues.SetValue<double>(drw, PL_JournalEntryTaxDetail.Amount, amount);
            DataRowViewValues.SetValue<double>(drw, PL_JournalEntryTaxDetail.Tax, tax);
            DataRowViewValues.SetValue<bool>(drw, PL_JournalEntryTaxDetail.BankRestraint, bankRestraint);
            DataRowViewValues.SetValue<bool>(drw, PL_JournalEntryTaxDetail.Deduction, deduction);
            DataRowViewValues.SetValue<bool>(drw, PL_JournalEntryTaxDetail.Restraint, restraint);
            DataRowViewValues.SetValue<string>(drw, PL_JournalEntryTaxDetail.RestraintCode, restraintcode);
            DataRowViewValues.SetValue<double>(drw, PL_JournalEntryTaxDetail.RestraintAmount, restraintamount);
            UpdateCastleTax();

            return DataRowViewValues.GetValue<int>(drw, PL_JournalEntryTaxDetail.Line);
        }

        protected override bool OnEnableToolbarButtons(ToolStripButton button)
        {
            if (button.Name == "tbnEdit")
                return dbManager.GetColumn<bool>(PL_JournalEntry.Editable, 0) || !AccountingPref.LockDocumentFromSale;

            return base.OnEnableToolbarButtons(button);
        }

        private void AddListDocNo(List<string> listDocNo)
        {
            foreach (DataGridViewRow dr in dgwJournalEntries.Rows)
            {
                string docNo;
                if (!dr.IsNewRow)
                {
                    docNo = DataGridViewRowValues.GetValue<string>(dr, PL_JournalEntryDetail.DocumentNo);
                    if (docNo != "")
                        listDocNo.Add(docNo);
                }
            }
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            DRJETemplate drJETemplate = new DRJETemplate();
            RRJETemplateDetail rrJEDetail = new RRJETemplateDetail();
            RRJETemplateTaxDetail rrJETaxDetail = new RRJETemplateTaxDetail();

            IsInLoad = true;
            if (dgwJournalEntries.RowCount > 1)
                dgwJournalEntries.Clear();

            if (drJETemplate.Find(cbbTemplate.GetValue<string>()))
            {
                //txtDescription.Text = drJETemplate.GetValue<string>(PL_JETemplate.Description);
                cbbTaxRegister.SelectedValue = drJETemplate.GetValue<TaxRegisterType>(PL_JETemplate.TaxRegister).Int();
                cbbDocType.SelectedValue = drJETemplate.GetValue<InvoiceType>(PL_JETemplate.InvoiceType).Int();

                if (!drJETemplate.GetValue<string>(PL_JETemplate.Type).IsEmpty())
                {
                    cbbType.SelectedValue = drJETemplate.GetValue<string>(PL_JETemplate.Type);
                    rdrCode.Text = drJETemplate.GetValue<string>(PL_JETemplate.Code);
                }

                if (rrJEDetail.Find(cbbTemplate.GetValue<string>()))
                    for (int t = 0; t < rrJEDetail.Count; t++)
                    {
                        AddNewRow(rrJEDetail.GetValue<string>(PL_JETemplateDetail.Type, t),
                                    rrJEDetail.GetValue<string>(PL_JETemplateDetail.DocumentNo, t),
                                    rrJEDetail.GetValue<string>(PL_JETemplateDetail.Code, t),
                                    rrJEDetail.GetValue<double>(PL_JETemplateDetail.From, t),
                                    rrJEDetail.GetValue<double>(PL_JETemplateDetail.To, t),
                                    rrJEDetail.GetValue<string>(PL_JETemplateDetail.Description, t),
                                    false, false, "");
                    }

                if (rrJETaxDetail.Find(cbbTemplate.GetValue<string>()))
                    for (int t = 0; t < rrJETaxDetail.Count; t++)
                    {
                        AddCastleRow(rrJETaxDetail.GetValue<string>(PL_JETemplateTaxDetail.TaxCode, t),
                                    0,
                                    0,
                                    false,
                                    rrJETaxDetail.GetValue<bool>(PL_JETemplateTaxDetail.Deduction, t),
                                    false,
                                    "",
                                    0);
                    }

            }
            IsInLoad = false;
            if (dgwJournalEntries.RowCount > 1)
            {
                dgwJournalEntries.DataGridViewRowValidating -= new DataGridViewCellCancelEventHandler(dgwJournalEntries_DataGridViewRowValidating);
                dgwJournalEntries.CurrentCell = dgwJournalEntries[PL_JETemplateDetail.From, 0];
                dgwJournalEntries.DataGridViewRowValidating += new DataGridViewCellCancelEventHandler(dgwJournalEntries_DataGridViewRowValidating);
            }

            UpdateTypeOnRow();
            UpdateCodeOnRow();
            UpdateDocumentOnRow();
            UpdateDescriptionOnRow();
            SplitCastleOnRow();
        }

        private void UpdateTypeOnRow()
        {
            if (string.IsNullOrEmpty(cbbType.GetValue<string>()))
                return;

            foreach (DataGridViewRow dr in dgwJournalEntries.Rows)
            {
                if (dr.IsNewRow)
                    continue;
             
                string type = DataGridViewRowValues.GetValue<string>(dr, PL_JournalEntryDetail.Type);
                if (dRMasterType.Find(type))
                {
                    if (dRMasterType.GetValue<MasterTypes>(PL_MasterType.MasterType) == MasterTypes.E_Other ||
                        dRMasterType.GetValue<MasterTypes>(PL_MasterType.MasterType) == MasterTypes.E_Condominium)
                    {
                        DataGridViewRowValues.SetValue<string>(dr, PL_JournalEntryDetail.Type, cbbType.GetValue<string>());
                    }
                }
            }
        }

        private void UpdateCodeOnRow()
        {
            if (string.IsNullOrEmpty(rdrCode.Text))
                return;

            foreach (DataGridViewRow dr in dgwJournalEntries.Rows)
            {
                if (dr.IsNewRow)
                    continue;

                string type = DataGridViewRowValues.GetValue<string>(dr, PL_JournalEntryDetail.Type);
                if (type == cbbType.GetValue<string>())
                {
                    DataGridViewRowValues.SetValue<string>(dr, PL_JournalEntryDetail.Code, rdrCode.Text);
                }
            }
        }

        private void UpdateDocumentOnRow()
        {
            if (txtDocNo.Text.IsEmpty() && txtInvoice.Text.IsEmpty())
                return;

            foreach (DataGridViewRow dr in dgwJournalEntries.Rows)
            {
                if (dr.IsNewRow)
                    continue;

                string type = DataGridViewRowValues.GetValue<string>(dr, PL_JournalEntryDetail.Type);
                if (dRMasterType.Find(type) && dRMasterType.GetValue<bool>(PL_MasterType.CopyDocNo))
                {
                    DataGridViewRowValues.SetValue<string>(dr, PL_JournalEntryDetail.DocumentNo, txtDocNo.Text);
                    DataGridViewRowValues.SetValue<string>(dr, PL_JournalEntryDetail.InvoiceNo, txtInvoice.Text);
                }
            }
        }

        private bool HasRowAtZero()
        {
            foreach (DataGridViewRow dr in dgwJournalEntries.Rows)
            {
                if (dr.IsNewRow)
                    continue;
                if (DataGridViewRowValues.GetValue<double>(dr, PL_JournalEntryDetail.From) == 0 &&
                    DataGridViewRowValues.GetValue<double>(dr, PL_JournalEntryDetail.To) == 0)
                    return true;
            }

            return false;
        }

        private bool HasEmptyRow()
        {
            int rowFound = 0;
            foreach (DataGridViewRow dr in dgwJournalEntries.Rows)
            {
                if (dr.IsNewRow)
                    continue;
                if (string.IsNullOrEmpty(DataGridViewRowValues.GetValue<string>(dr, PL_JournalEntryDetail.Type)))
                    continue;
                if (DataGridViewRowValues.GetValue<double>(dr, PL_JournalEntryDetail.From) == 0 &&
                    DataGridViewRowValues.GetValue<double>(dr, PL_JournalEntryDetail.To) == 0)
                    continue;
                rowFound++;
            }

            return rowFound == 0;
        }

        private bool HasEmptyTaxRow()
        {
            foreach (DataGridViewRow dr in dgwCastleTax.Rows)
            {
                if (dr.IsNewRow)
                    continue;
                if (string.IsNullOrEmpty(DataGridViewRowValues.GetValue<string>(dr, PL_JournalEntryTaxDetail.TaxCode)))
                    return true;
            }
            return false;
        }

        private void UpdateDescriptionOnRow()
        {
            foreach (DataGridViewRow dr in dgwJournalEntries.Rows)
            {
                if (dr.IsNewRow)
                    continue;

                string txt = string.Format("n° {0} del {1}", txtDocNo.Text, ctbDocDate.Text);
                string desc = DataGridViewRowValues.GetValue<string>(dr, PL_JournalEntryDetail.Description);
                int pos = desc.IndexOf("n°",StringComparison.CurrentCultureIgnoreCase);
                if (pos >= 0)
                {
                    desc = desc.Substring(0, pos) + txt;
                    DataGridViewRowValues.SetValue<string>(dr, PL_JournalEntryDetail.Description, desc);
                }
            }
        }

        private void ChangeCloseStatusRow(bool status)
        {
            bForcedCloseOpen = true;
            foreach (DataGridViewRow dr in dgwJournalEntries.Rows)
                if (!dr.IsNewRow)
                    DataGridViewRowValues.SetValue<bool>(dr, PL_JournalEntryDetail.Close, status);
        }

        private void ckbClose_CheckedChanged(object sender, EventArgs e)
        {
        }

        private void ckbClose_CheckStateChanged(object sender, EventArgs e)
        {
            if (DocumentMode == DBMode.Browse || IsNew || FromPrepareAuxData)
                return;

            if (MyMessageBox(
                    ckbClose.Checked
                        ? Properties.Resources.Msg_CloseJE
                        : Properties.Resources.Msg_OpenJE,
                     Properties.Resources.Warning, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == System.Windows.Forms.DialogResult.Yes)
                ChangeCloseStatusRow(ckbClose.Checked);
            else
                ckbClose.Checked = !ckbClose.Checked;
        }

        private string CreateListDocNo(ListView.ListViewItemCollection list)
        {
            string docs = string.Empty;
            foreach (ListViewItem lvi in list)
                if (lvi.Checked)
                    docs += lvi.SubItems[0].Text.Replace(" ", string.Empty) + " ";
            return docs;
        }

        private void CreateTaxRow(object sender, EventArgs e)
        {
            dgwJournalEntries.CommitEdit(DataGridViewDataErrorContexts.Commit);
            double colFrom = DataGridViewRowValues.GetValue<double>(dgwJournalEntries.CurrentRow, PL_JournalEntryDetail.From);
            double colTo = DataGridViewRowValues.GetValue<double>(dgwJournalEntries.CurrentRow, PL_JournalEntryDetail.To);

            if (colTo > 0)
            { 
                AddNewRow(AccountingPref.SaleTax, "", "", 10, 20, "desc", false, false, "");
            }
            else
            { 
            }
        }

        private void dgwJournalEntries_DataGridViewDoubleClickCell(object sender, DataGridViewDoubleClickArgs e)
        {
            if (e.ColumnName == PL_JournalEntryDetail.Code.Name)
            {
                string typeCode = dgwJournalEntries.GetValue<string>(e.Row, PL_JournalEntryDetail.Type);
                if (dRMasterType.Find(typeCode))
                {
                    if (dRMasterType.GetValue<bool>(PL_MasterType.IsAccountingType))
                    {
                        Plumber.Accounting.Forms.AccountingMasters frm = (Plumber.Accounting.Forms.AccountingMasters)GlobalInfo.OpenForm("Plumber.Plumber.Accounting.Forms.AccountingMasters", false);
                        string type = dgwJournalEntries.GetValue<string>(e.Row, PL_Masters.Type);
                        frm.FindRecord(new RadarMasterParam(type, e.CellValue));
                    }
                    else
                    {
                        Plumber.Masters.Forms.Masters frm = (Plumber.Masters.Forms.Masters)GlobalInfo.OpenForm("Plumber.Plumber.Masters.Forms.Masters", false);
                        string type = dgwJournalEntries.GetValue<string>(e.Row, PL_Masters.Type);
                        frm.FindRecord(new RadarMasterParam(type, e.CellValue));
                    }
                }
            }
        }

        public string dgwJournalEntries_Code(object sender, DataGridViewCellValidatingEventArgs e)
        {
            string value;
            IRadarParameters iParam = jec_Code.RadarForm.GetRadarParameters(e.FormattedValue.ToString());
            e.Cancel = !jec_Code.RadarForm.ValidateValue(iParam, out value);
            return value;
        }

        private void dgwJournalEntries_FromAmountChange(object sender, DataGridViewCellEventArgs e)
        {
            if (dgwJournalEntries.RowCount == 3)
            {
                int rowToChange = e.RowIndex == 1 ? 0 : 1;
                double valFrom = dgwJournalEntries.GetValue<double>(e.RowIndex, PL_JETemplateDetail.From);
                double valTo = dgwJournalEntries.GetValue<double>(rowToChange, PL_JETemplateDetail.To);
                if (valFrom != valTo)
                    dgwJournalEntries.SetValue<double>(rowToChange, PL_JETemplateDetail.To, valFrom);
            }
            CalculateTotal();
        }

        private void dgwJournalEntries_ToAmountChange(object sender, DataGridViewCellEventArgs e)
        {
            if (dgwJournalEntries.RowCount == 3)
            {
                int rowToChange = e.RowIndex == 1 ? 0 : 1;
                double valTo = dgwJournalEntries.GetValue<double>(e.RowIndex, PL_JETemplateDetail.To);
                double valFrom = dgwJournalEntries.GetValue<double>(rowToChange, PL_JETemplateDetail.From);
                if (valFrom != valTo)
                    dgwJournalEntries.SetValue<double>(rowToChange, PL_JETemplateDetail.From, valTo);
            }
            CalculateTotal();
        }

        private void dgwJournalEntries_Type(object sender, DataGridViewCellEventArgs e)
        {
            DoChangingRow(e);

            if (dgwJournalEntries[PL_JournalEntryDetail.DocumentNo].ReadOnly)
                dgwJournalEntries.SetValue<string>(e.RowIndex, PL_JournalEntryDetail.DocumentNo, "");
            if (dgwJournalEntries[PL_JournalEntryDetail.Description].ReadOnly)
                dgwJournalEntries.SetValue<string>(e.RowIndex, PL_JournalEntryDetail.Description, "");
        }


        private void DoChangingRow(DataGridViewCellEventArgs e)
        {
            string typeCode = dgwJournalEntries.GetValue<string>(e.RowIndex, PL_JournalEntryDetail.Type);
            dgwJournalEntries[PL_JournalEntryDetail.Code].ReadOnly = string.IsNullOrEmpty(typeCode);
            dgwJournalEntries[PL_JournalEntryDetail.From].ReadOnly = string.IsNullOrEmpty(typeCode);
            dgwJournalEntries[PL_JournalEntryDetail.To].ReadOnly = string.IsNullOrEmpty(typeCode);

            if (string.IsNullOrEmpty(typeCode))
                return;

            RadarMasterForm.Module module = RadarMasterForm.Module.All;
            if (dRMasterType.Find(typeCode))
            {
                module = dRMasterType.GetValue<bool>(PL_MasterType.IsAccountingType)
                            ? RadarMasterForm.Module.Accounting
                            : RadarMasterForm.Module.Master;
            }
            jec_Code.AttachCodeType(typeCode);

            if (jec_Code.RadarForm != null)
            {
                jec_Code.RadarForm.FilterType = typeCode;
                ((RadarMasterForm)jec_Code.RadarForm).ModuleType = module;
            }
            else
                jec_Code.RadarForm = new RadarMasterForm(typeCode, module);

            if (dRMasterType.Find(typeCode))
                dgwJournalEntries[PL_JournalEntryDetail.Code].ReadOnly = dRMasterType.GetValue<CodeMode>(PL_MasterType.CodeMode) == CodeMode.E_IsEmpty;
            else
                dgwJournalEntries[PL_JournalEntryDetail.Code].ReadOnly = false;

            if (dgwJournalEntries[PL_JournalEntryDetail.Code].ReadOnly)
                dgwJournalEntries.SetValue<string>(e.RowIndex, PL_JournalEntryDetail.Code, "");

            dgwJournalEntries[PL_JournalEntryDetail.Description].ReadOnly = string.IsNullOrEmpty(dgwJournalEntries.GetValue<string>(e.RowIndex, PL_JournalEntryDetail.Type));
            dgwJournalEntries[PL_JournalEntryDetail.DocumentNo].ReadOnly = dRMasterType.GetValue<bool>(PL_MasterType.CanReceiveInvoice);        
        }

        private DataGridViewRow FindPrimaryRow(string fromType, string fromCode)
        {
            foreach (DataGridViewRow dr in dgwJournalEntries.Rows)
            {
                if (!dr.IsNewRow)
                {
                    if (DataGridViewRowValues.GetValue<string>(dr, PL_JournalEntryDetail.Type) == fromType &&
                        DataGridViewRowValues.GetValue<string>(dr, PL_JournalEntryDetail.Code) == fromCode)
                        return dr;
                }
            }
            return null;
        }

        private bool GetRowClosed()
        {
            bool isClose = true;
            bool atLeastOne = false;

            foreach (DataGridViewRow dr in dgwJournalEntries.Rows)
                if (!dr.IsNewRow && DataGridViewRowValues.GetValue<string>(dr, PL_JournalEntryDetail.Code) != "")
                {
                    isClose &= DataGridViewRowValues.GetValue<bool>(dr, PL_JournalEntryDetail.Close);
                    atLeastOne = true;
                }
            return isClose && atLeastOne;
        }

        private void cbbType_SelectedValueChanged(object sender, EventArgs e)
        {
            CodeMode codeMode = CodeMode.E_MustExists;
            if (cbbType.GetValue<string>() == null)
                return;

            if (dRMasterType.Find(cbbType.GetValue<string>()))
            {
                codeMode = dRMasterType.GetValue<CodeMode>(PL_MasterType.CodeMode);
                //masterType = dRMasterType.GetValue<MasterTypes>(PL_MasterType.MasterType);
            }

            if (codeMode == CodeMode.E_IsEmpty)
            {
                rdrCode.Enabled = false;
                rdrCode.DeattachAll();
            }
            else
            {
                rdrCode.ReattachCodeType(cbbType.GetValue<string>());
                rdrCode.Enabled = true;
                rdrCode.RadarForm.FilterType = cbbType.GetValue<string>();
            }
            
            UpdateTypeOnRow();
            CheckDuplicateDocument();
        }

        private void CheckDuplicateDocument()
        {
            if (rdrCode.IsEmpty || string.IsNullOrEmpty(txtDocNo.Text) || string.IsNullOrEmpty(cbbType.GetValue<string>()))
                return;

            if (dRJETotByType.Find(txtDocNo.Text, cbbType.GetValue<string>(), rdrCode.Text))
            {
                if (dRJETotByType.GetValue<string>(PL_JournalEntry.JournalNo) != fncJournalNo.Text)
                {
                    string mess = string.Format(Properties.Resources.Msg_DuplicateDoc, 
                        dRJETotByType.GetValue<string>(PL_JournalEntry.JournalNo),
                        cbbType.Text,
                        rdrCode.Text,
                        dRJETotByType.GetValue<DateTime>(PL_JournalEntry.DocumentDate).ToShortDateString());
                    MyMessageBox(mess, Properties.Resources.Warning, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
        }

        //private void codMaster_Validating(object sender, CancelEventArgs e)
        //{
        //    if (string.IsNullOrEmpty(cbbType.GetValue<string>()) || rdrCode.IsEmpty)
        //    {
        //        txtDescription.Text = string.Empty;
        //        return;
        //    }

        //    if (dRMaster.Find(cbbType.GetValue<string>(), rdrCode.Text))
        //        txtDescription.Text = dRMaster.GetValue<string>(PL_Masters.Description);
        //}

        private void dgwCastleTax_TaxCode(object sender, DataGridViewCellEventArgs e)
        {
            dgwCastleTax.NoMessage = true;
            dRTaxCode.Find(dgwCastleTax.GetValue<string>(e.RowIndex, PL_JournalEntryTaxDetail.TaxCode));
            dgwCastleTax.SetValue<double>(e.RowIndex, PL_JournalEntryTaxDetail.TaxPerc, dRTaxCode.GetValue<double>(PL_TaxCode.Percent));

            dgwCastleTax_Amount(sender, e);
            dgwCastleTax.NoMessage = false;
        }

        private void dgwCastleTax_Amount(object sender, DataGridViewCellEventArgs e)
        {
            dgwCastleTax.NoMessage = true;
            double amount = dgwCastleTax.GetValue<double>(e.RowIndex, PL_JournalEntryTaxDetail.Amount);
            double taxPerc = dgwCastleTax.GetValue<double>(e.RowIndex, PL_JournalEntryTaxDetail.TaxPerc);
            double restPerc = dgwCastleTax.GetValue<double>(e.RowIndex, PL_JournalEntryTaxDetail.RestraintPerc);
            bool hasRest = dgwCastleTax.GetValue<bool>(e.RowIndex, PL_JournalEntryTaxDetail.Restraint);

            if (hasRest && restPerc != 0)
            {
                double restraint = Math.Round(amount * restPerc / 100, 2);
                dgwCastleTax.SetValue<double>(e.RowIndex, PL_JournalEntryTaxDetail.RestraintAmount, restraint);
            }

            double tax = Math.Round(amount * taxPerc / 100, 2);
            dgwCastleTax.SetValue<double>(e.RowIndex, PL_JournalEntryTaxDetail.Tax, tax);
            dgwCastleTax.SetValue<double>(e.RowIndex, PL_JournalEntryTaxDetail.Total, amount + tax);
            SplitCastleOnRow();

            dgwCastleTax.NoMessage = false;
        }

        private void dgwCastleTax_Tax(object sender, DataGridViewCellEventArgs e)
        {
            dgwCastleTax.NoMessage = true;
            SplitCastleOnRow();
            dgwCastleTax.NoMessage = false;
        }

        private void dgwCastleTax_Total(object sender, DataGridViewCellEventArgs e)
        {
            dgwCastleTax.NoMessage = true;
            double total = dgwCastleTax.GetValue<double>(e.RowIndex, PL_JournalEntryTaxDetail.Total);
            double taxPerc = dgwCastleTax.GetValue<double>(e.RowIndex, PL_JournalEntryTaxDetail.TaxPerc);
            if (taxPerc != 0)
            {
                double amount = Math.Round(total / (100 + taxPerc) * 100, 2);
                dgwCastleTax.SetValue<double>(e.RowIndex, PL_JournalEntryTaxDetail.Amount, amount);
                dgwCastleTax.SetValue<double>(e.RowIndex, PL_JournalEntryTaxDetail.Tax, total - amount);
                SplitCastleOnRow();
            }
            dgwCastleTax.NoMessage = false;
        }


        private void dgwCastleTax_Restraint(object sender, DataGridViewCellEventArgs e)
        {
            dgwCastleTax.NoMessage = true;
            if (!dgwCastleTax.GetValue<bool>(e.RowIndex, PL_JournalEntryTaxDetail.Restraint))
            {
                dgwCastleTax.SetValue<double>(e.RowIndex, PL_JournalEntryTaxDetail.RestraintPerc, 0);
                dgwCastleTax.SetValue<string>(e.RowIndex, PL_JournalEntryTaxDetail.RestraintCode, "");
                dgwCastleTax.SetValue<double>(e.RowIndex, PL_JournalEntryTaxDetail.RestraintAmount, 0);
            }

            bool IsReadonly = !dgwCastleTax.GetValue<bool>(e.RowIndex, PL_JournalEntryTaxDetail.Restraint);
            dgwCastleTax[PL_JournalEntryTaxDetail.RestraintAmount].ReadOnly = IsReadonly;
            dgwCastleTax[PL_JournalEntryTaxDetail.RestraintCode].ReadOnly = IsReadonly;
            dgwCastleTax_Amount(sender, e);

            dgwCastleTax.NoMessage = false;
        }

        private void dgwCastleTax_RestraintCode(object sender, DataGridViewCellEventArgs e)
        {
            dgwCastleTax.NoMessage = true;
            dRTaxCode.Find(dgwCastleTax.GetValue<string>(e.RowIndex, PL_JournalEntryTaxDetail.RestraintCode));
            dgwCastleTax.SetValue<double>(e.RowIndex, PL_JournalEntryTaxDetail.RestraintPerc, dRTaxCode.GetValue<double>(PL_TaxCode.Percent));

            dgwCastleTax_Amount(sender, e);
            dgwCastleTax.NoMessage = false;
        }


        private void rdrCode_Validated(object sender, EventArgs e)
        {
            UpdateCodeOnRow();
            CheckDuplicateDocument();
        }

        private void txtDocNo_Validated(object sender, EventArgs e)
        {
            UpdateDocumentOnRow();
            UpdateDescriptionOnRow();
            CheckDuplicateDocument();
        }

        private void ctbDocDate_Validated(object sender, EventArgs e)
        {
            UpdateDescriptionOnRow();
        }

        private void SplitCastleOnRow()
        {
            double totAmount = 0, totTax = 0, totTotal = 0, totDeduc = 0, totRestr = 0, totInv = 0, totBankRest = 0;
            string restCode = "";
            foreach (DataGridViewRow dr in dgwCastleTax.Rows)
            {
                if (dr.IsNewRow)
                    continue;
                totAmount += DataGridViewRowValues.GetValue<double>(dr, PL_JournalEntryTaxDetail.Amount);
                totTax += DataGridViewRowValues.GetValue<double>(dr, PL_JournalEntryTaxDetail.Tax);
                totTotal += DataGridViewRowValues.GetValue<double>(dr, PL_JournalEntryTaxDetail.Total);
                if (DataGridViewRowValues.GetValue<bool>(dr, PL_JournalEntryTaxDetail.Deduction))
                    totDeduc += Math.Round(DataGridViewRowValues.GetValue<double>(dr, PL_JournalEntryTaxDetail.Total) / 1.21 * 0.04 ,2);
                if (DataGridViewRowValues.GetValue<bool>(dr, PL_JournalEntryTaxDetail.Restraint))
                {
                    totRestr += DataGridViewRowValues.GetValue<double>(dr, PL_JournalEntryTaxDetail.RestraintAmount);
                    restCode = DataGridViewRowValues.GetValue<string>(dr, PL_JournalEntryTaxDetail.RestraintCode);
                }
                if (DataGridViewRowValues.GetValue<bool>(dr, PL_JournalEntryTaxDetail.BankRestraint))

                    totBankRest += Math.Round(DataGridViewRowValues.GetValue<double>(dr, PL_JournalEntryTaxDetail.Total) / 1.22 * 0.08, 2);
            }
            totInv = totTotal - totDeduc - totRestr - totBankRest;

            foreach (DataGridViewRow dr in dgwJournalEntries.Rows)
            {
                if (dr.IsNewRow)
                    continue;
                string masterType = DataGridViewRowValues.GetValue<string>(dr, PL_JournalEntryDetail.Type);
                dRMasterType.Find(masterType);

                switch (dRMasterType.GetValue<MasterTypes>(PL_MasterType.MasterType))
                {
                    case MasterTypes.E_SaleInvoice:
                        switch (eInvoiceType.GetValue())
                        {
                            case InvoiceType.E_InvoiceEm:
                            case InvoiceType.E_DebitNoteEm:
                                DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, 0);
                                DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, totAmount);
                                break;
                            case InvoiceType.E_CreditNoteEm:
                                DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, totAmount);
                                DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, 0);
                                break;
                        }
                        break;
                    case MasterTypes.E_PurchaseInvoice:
                        switch (eInvoiceType.GetValue())
                        {
                            case InvoiceType.E_InvoiceRc:
                            case InvoiceType.E_DebitNoteRc:
                                DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, totAmount);
                                DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, 0);
                                break;
                            case InvoiceType.E_CreditNoteRc:
                                DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, 0);
                                DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, totAmount);
                                break;
                        }

                        break;
                    case MasterTypes.E_Tax:
                        if (eTaxRegister.GetValue() == TaxRegisterType.E_TaxSale)
                        {
                            switch (eInvoiceType.GetValue())
                            {
                                case InvoiceType.E_InvoiceEm:
                                case InvoiceType.E_DebitNoteEm:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, 0);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, totTax);
                                    break;
                                case InvoiceType.E_CreditNoteEm:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, totTax);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, 0);
                                    break;
                            }
                        }
                        else
                        {
                            switch (eInvoiceType.GetValue())
                            {
                                case InvoiceType.E_InvoiceRc:
                                case InvoiceType.E_DebitNoteRc:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, totTax);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, 0);
                                    break;
                                case InvoiceType.E_CreditNoteRc:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, 0);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, totTax);
                                    break;
                            }
                        }
                        break;
                    case MasterTypes.E_BankCash:
                        if (eTaxRegister.GetValue() == TaxRegisterType.E_TaxPurchase)
                        {
                            switch (eInvoiceType.GetValue())
                            {
                                case InvoiceType.E_InvoiceRc:
                                case InvoiceType.E_DebitNoteRc:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, 0);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, totTotal);
                                    break;
                                case InvoiceType.E_CreditNoteRc:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, totTotal);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, 0);
                                    break;
                            }
                        }
                        else
                        {
                            switch (eInvoiceType.GetValue())
                            {
                                case InvoiceType.E_InvoiceEm:
                                case InvoiceType.E_DebitNoteEm:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, totTotal);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, 0);
                                    break;
                                case InvoiceType.E_CreditNoteEm:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, 0);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, totTotal);
                                    break;
                            }
                        }
                        break;
                    case MasterTypes.E_Deduction:
                        if (eTaxRegister.GetValue() == TaxRegisterType.E_TaxPurchase)
                        {
                            switch (eInvoiceType.GetValue())
                            {
                                case InvoiceType.E_InvoiceRc:
                                case InvoiceType.E_DebitNoteRc:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, 0);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, totDeduc);
                                    break;
                                case InvoiceType.E_CreditNoteRc:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, totDeduc);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, 0);
                                    break;
                            }
                        }
                        else
                        {
                            switch (eInvoiceType.GetValue())
                            {
                                case InvoiceType.E_InvoiceEm:
                                case InvoiceType.E_DebitNoteEm:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, totDeduc);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, 0);
                                    break;
                                case InvoiceType.E_CreditNoteEm:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, 0);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, totDeduc);
                                    break;
                            }

                        }
                        break;
                    case MasterTypes.E_Restraint:
                        if (totBankRest > 0)
                        {
                            switch (eInvoiceType.GetValue())
                            {
                                case InvoiceType.E_InvoiceEm:
                                case InvoiceType.E_DebitNoteEm:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, totBankRest);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, 0);
                                    break;
                                case InvoiceType.E_CreditNoteEm:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, 0);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, totBankRest);
                                    break;
                            }     
                        }
                        else
                        {
                            DataGridViewRowValues.SetValue<string>(dr, PL_JournalEntryDetail.Code, restCode);
                            if (eTaxRegister.GetValue() == TaxRegisterType.E_TaxPurchase)
                            {
                                switch (eInvoiceType.GetValue())
                                {
                                    case InvoiceType.E_InvoiceRc:
                                    case InvoiceType.E_DebitNoteRc:
                                        DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, 0);
                                        DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, totRestr);
                                        break;
                                    case InvoiceType.E_CreditNoteRc:
                                        DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, totRestr);
                                        DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, 0);
                                        break;
                                }
                            }
                            else
                            {
                                switch (eInvoiceType.GetValue())
                                {
                                    case InvoiceType.E_InvoiceEm:
                                    case InvoiceType.E_DebitNoteEm:
                                        DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, totRestr);
                                        DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, 0);
                                        break;
                                    case InvoiceType.E_CreditNoteEm:
                                        DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, 0);
                                        DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, totRestr);
                                        break;
                                }
                            }
                        }
                        break;
                    default:
                        if (eTaxRegister.GetValue() == TaxRegisterType.E_TaxSale)
                        {
                            switch (eInvoiceType.GetValue())
                            {
                                case InvoiceType.E_InvoiceEm:
                                case InvoiceType.E_DebitNoteEm:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, totTotal - totDeduc - totRestr- totBankRest);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, 0);
                                    totTotal = 0;
                                    break;
                                case InvoiceType.E_CreditNoteEm:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, 0);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, totTotal - totDeduc - totRestr - totBankRest);
                                    totTotal = 0;
                                    break;
                            }
                        }
                        else
                        {
                            switch (eInvoiceType.GetValue())
                            {
                                case InvoiceType.E_InvoiceRc:
                                case InvoiceType.E_DebitNoteRc:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, 0);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, totTotal);
                                    totTotal = 0;
                                    break;
                                case InvoiceType.E_CreditNoteRc:
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.To, totTotal);
                                    DataGridViewRowValues.SetValue<double>(dr, PL_JournalEntryDetail.From, 0);
                                    totTotal = 0;
                                    break;
                            }
                        }
                        break;
                }
            }
        }

        private void ClearEmptyDetailRow()
        {
            for (int t = dgwJournalEntries.RowCount-1; t >= 0; t--)
            {
                if (dgwJournalEntries.GetValue<double>(t, PL_JournalEntryDetail.From) ==0 &&
                    dgwJournalEntries.GetValue<double>(t, PL_JournalEntryDetail.To) ==0 &&
                    !dgwJournalEntries.Rows[t].IsNewRow)
                {
                  dgwJournalEntries.Rows.RemoveAt(t);
                }

            }
        }

        private void ctbDate_Validating(object sender, CancelEventArgs e)
        {
            if (dbManager.Status != DBMode.Browse && IsNew)
            {
                if (ctbDate.Today.Year != GlobalInfo.CurrentDate.Year)
                    MyMessageBox(string.Format(Properties.Resources.Msg_WrongYear, ctbDate.Today.ToShortDateString(), GlobalInfo.CurrentDate.Year),
                        Properties.Resources.Warning, MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        private void cbbDocType_SelectedValueChanged(object sender, EventArgs e)
        {
            SplitCastleOnRow();
            label7.Visible = eInvoiceType != null && eInvoiceType.GetValue() == InvoiceType.E_CreditNoteEm;
            txtInvoice.Visible = eInvoiceType != null && eInvoiceType.GetValue() == InvoiceType.E_CreditNoteEm;
            jec_InvoiceNo.Visible = txtInvoice.Visible;
        }
    }
    
}
